package algo_annotations.data;

import algo_annotations.data.annotations.GroupeAnno;
import algo_annotations.data.contrainte_superposition.GroupeSegmentFixe;
import algo_annotations.data.contrainte_superposition.SegmentFixe;
import algo_annotations.data.sites.GroupeSite;
import algo_annotations.data.sites.Site;
import algo_annotations.data.sites.SousGroupeSite;
import algo_annotations.heuristique.AlgoGenetic;
import algo_annotations.heuristique.TraitementSousGroupe;
import algo_annotations.params.Params_a;
import commons.params_appli.ParamsAppli;
import commons.data.I_Data;
import commons.logs.Logger;
import commons.spatialindex.simplegrid.SimpleGridSPI;
import commons.utils.primitive_geom.Rect_d;
import java.util.ArrayList;


public class Data_a implements I_Data{

	public Params_a params;
	public GroupeSite grpSite;
	public GroupeSegmentFixe grpSegment;

	public AlgoGenetic algo;
	private Rect_d rectEmprise;
	public Rect_d getRectEmprise() {return rectEmprise;}

	private SimpleGridSPI spiAnno_bestGroupe;


	public Data_a(Params_a params) {
		this.params = params;
	}

	public void initData(GroupeSite grpSite, GroupeSegmentFixe grpSegment) {
		this.grpSite = grpSite;
		this.grpSegment = grpSegment;

		rectEmprise = grpSite.getRectEmprise();
		rectEmprise.extendToRect(grpSegment.getRectEmprise());

		spiAnno_bestGroupe  = new SimpleGridSPI("SPI Anno best groupe", rectEmprise, SimpleGridSPI.getTailleFor(grpSite.nbSite()));
	}


	// En fin de traitement, (full traitement en automatique, ou groupe de step en interactif)
	//  on met a jour le SPI pour que l'affichage de la carte soit le bestGroupeAnno calculé
	public void majSPIAnno() {
		spiAnno_bestGroupe.clear();
		spiAnno_bestGroupe.addObjects(algo.getBestGroupeAnno().vAnno);
	}


	// ************* MODE INTERACTIF *******************************************

	public void createAndInitAlgo_interactif() {
		algo = new AlgoGenetic(this);
		algo.initAlgo();
		spiAnno_bestGroupe.clear();
		spiAnno_bestGroupe.addObjects(algo.getBestGroupeAnno().vAnno);
	}
	public void prepareTraitement_pass1_interactif() {
		algo.createTraitements_pass1();
	}

	// Construit les Traitement de la passe2 à partir des parametre en entrée
	// Peut etre appelé autant de fois que l'on veut, en mode interactif
	//  les traitements sont juste pour etre affiché en info dans la TOC, ils n'ont pas
	//  de taille vivier ni de nb d'iteration a ce stade
	public void prepareTraitement_pass2_interactif(double seuilNoteAnno, double seuilInteraction) {
		if (algo==null) {
			Logger.log_ERROR("L'algorithme n'a pas été initialisé !");
			return;
		}
		grpSite.prepareTraitement_pass2(algo.getBestGroupeAnno(), seuilNoteAnno, seuilInteraction);

		// 0, 0 : en mode interactif IHM, on recrée les traitements au cas par cas
		//  et c'est à ces moments la qu'on indique la taille vivier et le nb d'iter
		// là, l'appel ne sert qu'a avoir la liste des Traitements pour la mettre dans la TOC
		algo.createTraitements_pass2(0, 0);
	}
	// Idem, mais pour un unique site donné (sélectionné par l'utilisateur)
	public void prepareTraitement_pass2_interactif(Site site, double seuilNoteAnno, double seuilInteraction) {
		if (algo==null) {
			Logger.log_ERROR("L'algorithme n'a pas été initialisé !");
			return;
		}
		grpSite.prepareTraitement_pass2(site, seuilNoteAnno, seuilInteraction);

		// 0, 0 : en mode interactif IHM, on recrée les traitements au cas par cas
		//  et c'est à ces moments la qu'on indique la taille vivier et le nb d'iter
		// là, l'appel ne sert qu'a avoir la liste des Traitements pour la mettre dans la TOC
		algo.createTraitements_pass2(0, 0);
	}

	// avec paramètres issus du params pour la pass1
	public void initAlgo_forSousGroupe(SousGroupeSite sgs) {
		initAlgo_forSousGroupe (sgs, params.algo_tailleVivier_pass1, params.algo_nbIter_pass1);
	}
	public void initAlgo_forSousGroupe(SousGroupeSite sgs, int tailleVivier, int nbIter) {
		if (algo == null) {
			Logger.log_ERROR("Algo non initialisé");
			return;
		}
		TraitementSousGroupe trt = algo.createTraitementSousGroupeSite(sgs, tailleVivier, nbIter);
		algo.startTraitementSousGroupe(trt);
	}
	public void step_forCurrentSousGroupe() {
		if (algo == null) return;
		algo.step();
	}



	// Appelé surtout par les couches pour le dessin
	// Renvoie les données d'un certain type, a minima tous ceux à l'intérieur d'un rectangle fourni
	public ArrayList getData (DataType dataType, Rect_d rectVisu) {
		switch(dataType) {

			// les annos du meilleur groupe
			case ANNO_A:
				if (algo==null || algo.getBestGroupeAnno()==null)
					return null;
				else
					return spiAnno_bestGroupe.getObjectsThatMayIntersectWith(rectVisu);

			case SITE_A:
				return grpSite.getSitesThaMayIntersectWith(rectVisu);

			case SEGMENT_NOOPTIM_A:
				return grpSegment.getSegNonOptimThaMayIntersectWith(rectVisu);

			case SEGMENT_OPTIM_A:
				return grpSegment.getSegOptimThaMayIntersectWith(rectVisu);
			
			case ZONE:
				return params.vZone;
				
			default: assert(false); return null;
		}
	}


	public ArrayList<SegmentFixe> getAllSegments_optim() {
		return grpSegment.vSegment_optimise;
	}
	public ArrayList<SegmentFixe> getAllSegments_noOptim() {
		return grpSegment.vSegment;
	}
	public GroupeAnno getBestGroupeAnno() {
		return algo.getBestGroupeAnno();
	}


}
